/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package analiseSintatica.Regras.DeclaracoesIniciais;

import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSemantica.Tipos.TipoSemantico;
import analiseSemantica.Tipos.TiposSemanticos;
import analiseSemantica.estruturadedados.Struct;
import analiseSemantica.estruturadedados.Typedef;
import analiseSintatica.AnalisadorSintatico;
import analiseSintatica.ErroSintaticoException;
import analiseSintatica.Regras.Regra;
import analiseSintatica.Regras.Tipos.RegraTipoPrimitivo;
import analiseSintatica.Regras.Tipos.RegraStruct;
import java.util.LinkedList;

/**
 *
 * @author Dede do Bem
 * 
 * <typedef> ::= typedef (<tipo_primitivo> | <struct>) identificador ";" 
 */
public class RegraTypedef extends Regra {

    protected static Regra instancia;

    protected String estrutura = "typedef (<tipo_primitivo> | <struct>) identificador ';'";
    RegraTipoPrimitivo tipoPrimitivo;
    RegraStruct struct;


    /**
     * Construtor privado necessario ao singleton
     */
    private RegraTypedef() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraTypedef getInstance() {
        if (instancia == null) {
            instancia = new RegraTypedef();
        }
        return (RegraTypedef) instancia;
    }

    public TiposSemanticos analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {
       
    	listaTokens.removeFirst();
    	if(listaContem(RegraTipoPrimitivo.getInstance().getPrimeiro(), listaTokens.getFirst())){
    		TipoSemantico tipoprimitivo = RegraTipoPrimitivo.getInstance().analisar(listaTokens).removeTipos();
			Typedef typedef  = new Typedef(listaTokens.getFirst().getLexema(), (String)tipoprimitivo.getTipo());
			AnalisadorSintatico.escopoatual.put(listaTokens.getFirst().getLexema(), typedef);
	   	}else if(listaContem(RegraStruct.getInstance().getPrimeiro(), listaTokens.getFirst())){
	   		TiposSemanticos tiposstruct = RegraStruct.getInstance().analisar(listaTokens);
	   		if(tiposstruct != null){
	   			TipoSemantico tipostruct = tiposstruct.removeTipos();
	   			Struct temp = (Struct)tipostruct.getTipo();
	   			temp.setLexema(listaTokens.getFirst().getLexema());
	   			AnalisadorSintatico.escopoatual.put(listaTokens.getFirst().getLexema(), temp);
	   		}
	   	}else{
	   		ErroSintaticoException e = new ErroSintaticoException();
	   		e.addErros("Tipo primitivo ou Struct esperada antes do token " + listaTokens.getFirst().getLexema(), estrutura, listaTokens.getFirst().getLinha());
	   		throw e;
	   	}
    	reconheceToken(listaTokens, "identificador", estrutura);
    	reconheceLexema(listaTokens, "delimitador", ";", estrutura);     
    	return null;     
    }

    @Override
    protected void setPrimeiro() {
        this.primeiro.add("typedef");
    }
}


